

% houseA -> houseBC


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% INIT

% parameters
NCOMP = 1; % number of mixture components
USE_WEEKEND = 0; % including weekend tag in models
PRINT_ALL = 0; % print all cluster divergence scores
USE_HEURISTIC = 1; % use one-to-one heuristic

% path
oldPath = path;
addpath(genpath('../../data/ours/'));

% meta-feature labels
fid = fopen('mflabels.txt');
C = textscan(fid, '%d %s');
fclose(fid);
metafeatureIDs = C{1};
metafeatureLABELs = C{2};
clear C;
numMetafeatures = length(metafeatureIDs);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  TRAIN  %
%                                                                         %
%  A meta-feature classifier is built by computing a MoG for each sensor  %
%  and grouping these models by meta-feature. These clusters represent    %
%  our model for each meta-feature.                                       %
%                                                                         %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

load firings_BC_notmerged_sec.txt;
if ~USE_WEEKEND,
  firings_BC_notmerged_sec = firings_BC_notmerged_sec(:,1:3);
end
load mfmap_BC_notmerged.txt;
sensorIDs_BC_notmerged = mfmap_BC_notmerged(:,1);
numSensors_BC_notmerged = length(sensorIDs_BC_notmerged);

allmog_BC_notmerged = cell(numSensors_BC_notmerged,1);
mf_clusters_BC_notmerged = cell(numMetafeatures,1);

fprintf('Computing mixture models for sensors of house BC.\n');

for idx=1:numSensors_BC_notmerged,
  X = firings_BC_notmerged_sec(firings_BC_notmerged_sec(:,1)==sensorIDs_BC_notmerged(idx),2:end);
  allmog_BC_notmerged{idx} = gm_process_sensor(X, 'Blue', 0, NCOMP);
end

fprintf('Computing meta-feature clusters for house BC.\n');

for idx=1:numMetafeatures,
  mog_ids = mfmap_BC_notmerged(:,2)==metafeatureIDs(idx);
  fprintf('Meta-feature %2d (%s): %d sensors.\n', ...
      metafeatureIDs(idx),metafeatureLABELs{idx},sum(mog_ids));
  if sum(mog_ids) == 0,
    % no sensors corresponding to this meta-feature
    mf_clusters_BC_notmerged{idx} = cell(0);
  else
    mf_clusters_BC_notmerged{idx} = allmog_BC_notmerged(mog_ids);
  end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  TEST  %
%                                                                         %
%  Find for each 'anonymous' cluster (meta-feature of house A) the        %
%  best 'candidate' match (meta-feature of house B).                      %
%                                                                         %
%  The mapping is a function but has no inverse: multiple anonymous       %
%  clusters can be matched to the same candidate cluster.                 %
%                                                                         %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

load firings_A_sec.txt;
if ~USE_WEEKEND,
  firings_A_sec = firings_A_sec(:,1:3);
end
load mfmap_A.txt;
sensorIDs_A = mfmap_A(:,1);
numSensors_A = length(sensorIDs_A);

fprintf('\nComputing mixture models for sensors of house A.\n');

allmog_A = cell(numSensors_A,1);
for idx=1:numSensors_A,
  X = firings_A_sec(firings_A_sec(:,1)==sensorIDs_A(idx),2:end);
  allmog_A{idx} = gm_process_sensor(X, 'Blue', 0, NCOMP);
end

fprintf('Computing meta-feature clusters for house A.\n');

mf_clusters_A = cell(numMetafeatures,1);
for idx=1:numMetafeatures,
  mog_ids = mfmap_A(:,2)==metafeatureIDs(idx);
  fprintf('Meta-feature %2d (%s): %d sensors.\n', ...
      metafeatureIDs(idx),metafeatureLABELs{idx},sum(mog_ids));
  if sum(mog_ids) == 0,
    % no sensors corresponding to this meta-feature
    mf_clusters_A{idx} = cell(0);
  else
    mf_clusters_A{idx} = allmog_A(mog_ids);
  end
end

if USE_HEURISTIC,
  
  fprintf('\nFinding best matches for houseA->houseBC (heuristic).\n');

  anonymousClusters = mf_clusters_A;
  candidateClusters = mf_clusters_BC_notmerged;

  availableAnonymous = ones(length(anonymousClusters),1);
  availableCandidates = ones(length(candidateClusters),1);

  for idx=1:length(anonymousClusters),
    if isempty(anonymousClusters{idx}),
      availableAnonymous(idx) = 0;
    end
  end

  for idx=1:length(candidateClusters),
    if isempty(candidateClusters{idx}),
      availableCandidates(idx) = 0;
    end
  end

  while sum(availableAnonymous) > 0,

    if sum(availableCandidates) == 0,
      availableCandidates = ones(length(candidateClusters),1);
      for idx=1:length(candidateClusters),
        if isempty(candidateClusters{idx}),
          availableCandidates(idx) = 0;
        end
      end
    end

    matchingScores = inf(length(anonymousClusters),1);

    minDiv = inf;
    ordAnonymous = inf;
    ordCandidate = inf;

    % for each anonymous cluster still to be processed
    for idxAnonymous=1:length(anonymousClusters),
      if ~availableAnonymous(idxAnonymous),
        continue;
      end

      anonymous = anonymousClusters{idxAnonymous};    
      curOrdCandidate = inf;
      curMinDiv = inf;

      % compute divergence to all available candidates
      for idxCandidate=1:length(candidateClusters),
        if ~availableCandidates(idxCandidate),
          continue;
        end

        candidate = candidateClusters{idxCandidate};
        curDiv = compute_cluster_divergence(anonymous, candidate);

        if curDiv < curMinDiv,
          curMinDiv = curDiv;
          curOrdCandidate = idxCandidate;
        end      
      end

      if curMinDiv < minDiv,
        minDiv = curMinDiv;
        ordAnonymous = idxAnonymous;
        ordCandidate = curOrdCandidate;
      end
    end

    % print match with lowest score
    fprintf('%s/A -> %s/BC (%f)\n', ...
      metafeatureLABELs{ordAnonymous}, ...
      metafeatureLABELs{ordCandidate}, ...
      minDiv);

    % remove matched clusters from anonymous and candidate list
    availableAnonymous(ordAnonymous) = 0;
    availableCandidates(ordCandidate) = 0;

  end
  
else

  fprintf('\nFinding best matches for houseA->houseBC (normal).\n');

  % for each 'anonymous' cluster in houseA
  for idxAnonymous=1:length(mf_clusters_A),

    anonymous = mf_clusters_A{idxAnonymous};

    if isempty(anonymous),
      continue;
    end

    if PRINT_ALL,
      fprintf('Compute divergence scores for %s/A.\n', ...
        metafeatureLABELs{idxAnonymous});
    end

    minDiv = inf;
    ordCandidate = inf;

    % find best matching 'candidate' cluster from houseBC
    for idxCandidate=1:numMetafeatures,
      candidate = mf_clusters_BC_notmerged{idxCandidate};
      curDiv = compute_cluster_divergence(anonymous, candidate);

      if PRINT_ALL && curDiv ~= inf,
        fprintf('  -> %s/BC (%f)\n', ...
          metafeatureLABELs{idxCandidate}, ...
          curDiv);
      end

      if curDiv < minDiv,
        minDiv = curDiv;
        ordCandidate = idxCandidate;
      end
    end

    if isinf(ordCandidate),
      continue;
    else    
      fprintf('%s/A -> %s/BC (%f)\n', ...
        metafeatureLABELs{idxAnonymous}, ...
        metafeatureLABELs{ordCandidate}, ...
        minDiv);
    end

  end
  
end


% restore old MATLAB path
path(oldPath);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  RESULTS  %
%                                                                         %
%
%   meta-features
%
%   Computing meta-feature clusters for house BC.
%
%   Meta-feature  1 (KitchHeat): 4 sensors.
%   Meta-feature  2 (Toilet): 4 sensors.
%   Meta-feature  3 (BathroomDoor): 2 sensors.
%   Meta-feature  4 (Kitchen): 9 sensors.
%   Meta-feature  5 (KitchStor): 4 sensors.
%   Meta-feature  6 (Outside): 2 sensors.
%   Meta-feature  7 (SleepDoor): 2 sensors.
%   Meta-feature  8 (Sleep): 7 sensors.
%   Meta-feature  9 (Bathroom): 4 sensors.
%   Meta-feature 10 (Other): 1 sensors.
%
% 
%   Computing meta-feature clusters for house A.
%
%   Meta-feature  1 (KitchHeat): 1 sensors.
%   Meta-feature  2 (Toilet): 2 sensors.
%   Meta-feature  3 (BathroomDoor): 1 sensors.
%   Meta-feature  4 (Kitchen): 6 sensors.
%   Meta-feature  5 (KitchStor): 2 sensors.
%   Meta-feature  6 (Outside): 1 sensors.
%   Meta-feature  7 (SleepDoor): 1 sensors.
%   Meta-feature  8 (Sleep): 0 sensors.
%   Meta-feature  9 (Bathroom): 0 sensors.
%   Meta-feature 10 (Other): 0 sensors.
%
%
%   houseA -> houseBC (normal)
%
%   KitchHeat/A -> SleepDoor/BC (0.284794)
%   Toilet/A -> BathroomDoor/BC (0.211404)
%   BathroomDoor/A -> Bathroom/BC (0.255044)
%   Kitchen/A -> Kitchen/BC (0.840188)
%   KitchStor/A -> Kitchen/BC (0.895892)
%   Outside/A -> Outside/BC (0.329830)
%   SleepDoor/A -> Sleep/BC (0.273608)
%
%   houseA -> houseBC (one-to-one heuristic)
%
%   Toilet/A -> BathroomDoor/BC (0.215205)
%   BathroomDoor/A -> Bathroom/BC (0.267508)
%   KitchHeat/A -> SleepDoor/BC (0.269613)
%   SleepDoor/A -> Sleep/BC (0.273268)
%   Outside/A -> Outside/BC (0.325871)
%   Kitchen/A -> Kitchen/BC (0.834272)
%   KitchStor/A -> Other/BC (1.895406)
%                                                                         %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
